﻿using Micro.Core.Options;
using Micro.Core.Packages;
using Micro.Extensions.Logger.Options;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Serilog;
using Serilog.Events;
using Serilog.Filters;
using Serilog.Sinks.Grafana.Loki;

namespace Microsoft.Extensions.DependencyInjection
{
    public class LoggerPack : BasePackage
    {

        public override PackLevel Level => PackLevel.Core;

        public override IServiceCollection AddServices(IServiceCollection services)
        {
            IConfiguration configuration = services.GetConfiguration();
            SerilogOption serilogOption = new SerilogOption();
            configuration.GetSection("Serilog").Bind(serilogOption);
            services.AddSingleton(serilogOption);

            return services;
        }


        public override void UsePack(WebApplication app)
        {
            base.UsePack(app);
        }

        public override void UseHostBuilder(IHostBuilder hostBuilder, IServiceProvider services)
        {
            SerilogOption serilogOption = services.GetService<SerilogOption>()!;
            ServiceDiscoveryOption serviceDiscoveryOption = services.GetService<ServiceDiscoveryOption>()!;
            hostBuilder.UseSerilog((context, configure) =>
            {
                var config = context.Configuration;

                //ReadFromConfiguration(configure, context.Configuration);
                configure.ReadFrom.Configuration(context.Configuration).Enrich.FromLogContext().WriteTo.Console();


                string ApplicationName = serilogOption.ApplicationName ?? serviceDiscoveryOption.Id;
                string GrafanaLokiUrl = serilogOption.GrafanaLokiUrl;
                if (!string.IsNullOrWhiteSpace(ApplicationName) && !string.IsNullOrWhiteSpace(GrafanaLokiUrl))
                {
                    string WithPropertyName = serilogOption.WithPropertyName;
                    configure.Enrich.WithProperty(WithPropertyName, ApplicationName)
                    .WriteTo.GrafanaLoki(GrafanaLokiUrl);
                }
            });
        

            base.UseHostBuilder(hostBuilder, services);
        }

        private void ReadFromConfiguration(LoggerConfiguration configure,IConfiguration configuration)
        {
            configure.ReadFrom.Configuration(configuration)
               // 最小的日志输出级别
               //.MinimumLevel.Error()
               // 日志调用类命名空间如果以 Microsoft 开头，覆盖日志输出最小级别为 Information
               //.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
               .Enrich.FromLogContext()
               // 配置日志输出到文件，文件输出到当前项目的 logs 目录下
               .WriteTo.Logger(lc =>
               {
                   //lc.Filter.ByIncludingOnly(Matching.FromSource<JMS.JMSClient>())
                   //.WriteTo.File("logs/JMSClient Error/log.txt",
                   // outputTemplate: "{Timestamp:HH:mm:ss} {NewLine}{Message}{NewLine}{Exception}",
                   //    rollingInterval: RollingInterval.Day,
                   //    rollOnFileSizeLimit: true);
               })
              .WriteTo.Logger(lc =>
              {
                  lc.Filter.ByExcluding(e => e.Level == LogEventLevel.Error || e.Level == LogEventLevel.Debug)
                  .WriteTo.File("logs/normal/log.txt",
                   outputTemplate: "{Timestamp:HH:mm:ss} [{Level}] {SourceContext} {NewLine}{Message}{NewLine}{Exception}",
                      rollingInterval: RollingInterval.Day,
                      rollOnFileSizeLimit: true);
              })
               .WriteTo.Logger(lc =>
               {
                   lc.Filter.ByIncludingOnly(e => e.Level == LogEventLevel.Error)
                   .WriteTo.File("logs/errors/log.txt",
                    outputTemplate: "{Timestamp:HH:mm:ss} [{Level}] {SourceContext} {NewLine}{Message}{NewLine}{Exception}",
                       rollingInterval: RollingInterval.Day,
                       rollOnFileSizeLimit: true);
               })
                .WriteTo.Logger(lc =>
                {
                    lc.Filter.ByIncludingOnly(e => e.Level == LogEventLevel.Debug)
                    .WriteTo.File("logs/debugs/log.txt",
                     outputTemplate: "{Timestamp:HH:mm:ss} [{Level}] {SourceContext} {NewLine}{Message}{NewLine}{Exception}",
                        rollingInterval: RollingInterval.Day,
                        rollOnFileSizeLimit: true);
                });
        }
    }
}